using UFrame.DataPack;
using System.Collections.Generic;
using System;

public abstract class UserDataController
{
    protected DataCtrl m_dataCtrl = new DataCtrl();
    protected int Year
    {
        get
        {
            return System.DateTime.Now.Year;
        }
    }
    protected int YearMonth
    {
        get
        {
            return System.DateTime.Now.Year * 100 + System.DateTime.Now.Month;
        }
    }
    protected int YearMonthDay
    {
        get
        {
            return System.DateTime.Now.Year * 10000 + System.DateTime.Now.Month * 100 + System.DateTime.Now.Hour;
        }
    }
    protected int FlagBase
    {
        get
        {
            return 0;
        }
    }
    protected Dictionary<Int64, HashSet<Action>> m_dataChangeActions;

    public UserDataController()
    {
        m_dataCtrl.dataReloadEvent += OnDataReload;
        m_dataCtrl.dataChangeEvent += OnDataChanged;
        m_dataChangeActions = new Dictionary<long, HashSet<Action>>();
    }

    public DataCtrl GetDataCtrl()
    {
        return m_dataCtrl;
    }

    protected abstract void OnDataReload();

    protected virtual void OnDataChanged(int groupId, int id)
    {
        var key = (long)groupId << 32 + id;
        if(m_dataChangeActions.TryGetValue(key,out var actions))
        {
            foreach (var action in actions)
            {
                try
                {
                    action?.Invoke();
                }
                catch(Exception e)
                {
                    UnityEngine.Debug.LogException(e);
                }
            }
        }
    }

    public abstract void CollectGroup(HashSet<int> groupList);
    public void RegsitDataChangeEvent(int groupId, int id, System.Action onChange)
    {
        var key = (long)groupId << 32 + id;
        if(!m_dataChangeActions.TryGetValue(key,out var actions))
        {
            actions = m_dataChangeActions[key] = new HashSet<Action>();
        }
        actions.Add(onChange);
    }

    public void RemoveDataChangeEvent(int groupId, int id, System.Action onChange)
    {
        var key = (long)groupId << 32 + id;
        if (m_dataChangeActions.TryGetValue(key, out var actions))
        {
            actions.Remove(onChange);
        }
    }

    public void RegsitDataChangeEvent(System.Action<int, int> onChange)
    {
        if (onChange != null)
            m_dataCtrl.dataChangeEvent += onChange;
    }
    public void RemoveDataChangeEvent(System.Action<int, int> onChange)
    {
        if (onChange != null)
            m_dataCtrl.dataChangeEvent -= onChange;
    }
    public void DeSerializeFromJson(string json)
    {
        m_dataCtrl.ClearAll();
        m_dataCtrl.CopyFrom(json);
    }
    public string SerializeToJson()
    {
        return m_dataCtrl.SerializeToJson();
    }
    public void SetValue(int groupId, int id, string value, int flag = 0, int time = 0)
    {
        m_dataCtrl.SetData(groupId, id, value, flag, time);
    }
    public void SetValue(int groupId, int id, int value, int flag = 0, int time = 0)
    {
        m_dataCtrl.SetData(groupId, id, value.ToString(), flag, time);
    }
    public void SetValue(int groupId, int id, float value, int flag = 0, int time = 0)
    {
        m_dataCtrl.SetData(groupId, id, value.ToString("0.00"), flag, time);
    }
    public void SetValue(int groupId, int id, bool value, int flag = 0, int time = 0)
    {
        m_dataCtrl.SetData(groupId, id, value ? "1" : "0", flag, time);
    }
    public void SetValue<T>(int groupId, int id, T value, int flag = 0, int time = 0) where T : class, new()
    {
        m_dataCtrl.SetData(groupId, id, UnityEngine.JsonUtility.ToJson(value), flag, time);
    }
    public bool TryGetValue(int groupId, int id, out string value)
    {
        if (m_dataCtrl.TryGetDataValue(groupId, id, out value))
        {
            return true;
        }
        value = null;
        return false;
    }

    public bool TryGetValue(int groupId, int id, out int value)
    {
        if (m_dataCtrl.TryGetDataValue(groupId, id, out string strValue) && int.TryParse(strValue, out value))
        {
            return true;
        }
        value = 0;
        return false;
    }

    public bool TryGetValue(int groupId, int id, out bool value)
    {
        if (m_dataCtrl.TryGetDataValue(groupId, id, out string strValue) && !string.IsNullOrEmpty(strValue))
        {
            value = strValue != "0";
            return true;
        }
        value = false;
        return false;
    }

    public bool TryGetValue(int groupId, int id, out float value)
    {
        if (m_dataCtrl.TryGetDataValue(groupId, id, out string strValue) && float.TryParse(strValue, out value))
        {
            return true;
        }
        value = 0;
        return false;
    }

    public bool TryGetValue<T>(int groupId, int id, out T value) where T : class, new()
    {
        if (m_dataCtrl.TryGetDataValue(groupId, id, out string strValue))
        {
            value = UnityEngine.JsonUtility.FromJson<T>(strValue);
            return true;
        }
        value = default(T);
        return false;
    }
}
